/*
* Sun Public License Notice
*
* The contents of this file are subject to the Sun Public License
* Version 1.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://www.sun.com/
*
* The Original Code is Forte for Java, Community Edition. The Initial
* Developer of the Original Code is Sun Microsystems, Inc. Portions
* Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved.
*/
package org.openide.actions;
import java.util.*;
import org.openide.TopManager;
import org.openide.cookies.CompilerCookie;
import org.openide.cookies.ExecCookie;
import org.openide.compiler.CompilerTask;
import org.openide.compiler.CompilerJob;
import org.openide.compiler.Compiler;
import org.openide.execution.Executor;
import org.openide.windows.Workspace;
import org.openide.windows.WindowManager;
import org.openide.util.enum.ArrayEnumeration;
import org.openide.util.HelpCtx;
import org.openide.util.actions.CookieAction;
import org.openide.nodes.Node;
import org.openide.loaders.DataObject;
/** Execute a class.
* Is enabled if the only selected node implements
* {@link ExecCookie}.
* @see org.openide.execution
*
* @author Ian Formanek, Jaroslav Tulach, Jan Jancura
*/
public class ExecuteAction extends CookieAction {
/** generated Serialized Version UID */
static final long serialVersionUID = -1861936644244723970L;
// static ..........................................................................................
private static String workspace = "Running"; // NOI18N
/** should we run compilation before execution */
private static boolean runCompilation = true;
/** Switches to running workspace */
static void changeWorkspace () {
WindowManager dp = TopManager.getDefault ().getWindowManager ();
Workspace d = dp.findWorkspace (workspace);
if (d != null) d.activate ();
}
/**
* Get the name of the workspace in which execution is performed.
* By default, execution is performed in the "running" workspace.
* @return the workspace name
*/
public static String getWorkspace () {
return workspace;
}
/**
* Set the name of the workspace in which execution is performed.
* @param workspace the workspace name
*/
public static void setWorkspace (String workspace) {
ExecuteAction.workspace = workspace;
}
/** Set whether files should be compiled before execution.
* @param run <code>true</code> if they should
*/
public static void setRunCompilation (boolean run) {
runCompilation = run;
}
/** Test whether files will be compiled before execution.
* By default they will.
* @return <code>true</code> if they will be
*/
public static boolean getRunCompilation () {
return runCompilation;
}
// init ..........................................................................................
/* Needs exec cookie.
*/
protected Class[] cookieClasses () {
return new Class[] { ExecCookie.class };
}
/* Checks the cookies and starts them.
*/
protected void performAction (final Node[] activatedNodes) {
// do the compilation in different thread
new Thread () {
public void run () {
execute(activatedNodes, runCompilation, true);
}
/* JST: This check must be done in the ExecCookie.start method
if (!((ExecCookie)Cookies.getInstanceOf (cookie, ExecCookie.class)).isExecAllowed()) {
TopManager.getDefault().notify(
new NotifyDescriptor.Message(
java.text.MessageFormat.format (
topBundle.getString ("FMT_MSG_CannotExecute"),
new Object[] {
node.getDisplayName ()
}
),
NotifyDescriptor.WARNING_MESSAGE)
);
doRun = false;
}
*/
}.start ();
}
/* Mode any is enough.
*/
protected int mode () {
return MODE_ANY;
}
/* Human presentable name of the action. This should be
* presented as an item in a menu.
* @return the name of the action
*/
public String getName() {
return ActionConstants.BUNDLE.getString("Execute");
}
/* Help context where to find more about the acion.
* @return the help context for this action
*/
public HelpCtx getHelpCtx() {
return new HelpCtx (ExecuteAction.class);
}
protected String iconResource () {
return "/org/openide/resources/actions/execute.gif"; // NOI18N
}
// utility methods
/** Execute a list of items by cookie.
*
* @param execCookies list of {@link ExecCookie}s (any may be <code>null</code>)
*/
public static void execute(Iterator execCookies) {
while (execCookies.hasNext()) {
ExecCookie cookie = (ExecCookie) execCookies.next();
if (cookie != null) {
cookie.start();
}
}
}
/** Execute some data objects.
*
* @param dataObjects the data objects (should have {@link ExecCookie} on them if they are to be used)
* @param compileBefore <code>true</code> to compile before executing
* @return true if compilation succeeded or was not performed, false if compilation failed
*/
public static boolean execute(DataObject[] dataObjects, boolean compileBefore) {
// search all DataObjects with unique ExecCookies/StartCookies -
// - it is possible, that multiple activated nodes have the same exec cookie and
// we have to prevent running it multiple times
HashSet compile = new HashSet ();
HashSet execute = new HashSet ();
for (int i = 0; i < dataObjects.length; i++) {
ExecCookie exec = (ExecCookie) dataObjects[i].getCookie(ExecCookie.class);
if (exec != null) {
execute.add(exec);
if (compileBefore) {
CompilerCookie comp = (CompilerCookie) dataObjects[i].getCookie(CompilerCookie.Compile.class);
if (comp != null) {
compile.add(comp);
}
}
}
}
// compile
if (compileBefore) {
if (! AbstractCompileAction.compile(Collections.enumeration(compile),
AbstractCompileAction.findName(dataObjects))) {
return false;
}
}
// execute
execute(execute.iterator());
return true;
}
/** Execute some nodes.
*
* @param nodes the nodes (should have {@link ExecCookie} on them if they are to be used)
* @param compileBefore <code>true</code> to compile before executing
* @return true if compilation succeeded or was not performed, false if compilation failed
*/
public static boolean execute(Node[] nodes, boolean compileBefore) {
return execute(nodes, compileBefore, false);
}
/** Execute some nodes.
*
* @param nodes the nodes (should have {@link ExecCookie} on them if they are to be used)
* @param compileBefore <code>true</code> to compile before executing
* @param switchWorkspace <code>true</code> to switch workspace before executing
* @return true if compilation succeeded or was not performed, false if compilation failed
*/
private static boolean execute(Node[] nodes, boolean compileBefore, boolean switchWorkspace) {
// find all activatedNodes with unique ExecCookies/StartCookies -
// - it is possible, that multiple activated nodes have the same exec cookie and
// we have to prevent running it multiple times
HashSet compile = new HashSet ();
HashSet execute = new HashSet ();
for (int i = 0; i < nodes.length; i++) {
ExecCookie exec = (ExecCookie) nodes[i].getCookie(ExecCookie.class);
if (exec != null) {
execute.add(exec);
if (compileBefore) {
CompilerCookie comp = (CompilerCookie) nodes[i].getCookie(CompilerCookie.Compile.class);
if (comp != null) {
compile.add(comp);
}
}
}
}
// compile
if (compileBefore) {
if (! AbstractCompileAction.compile(Collections.enumeration(compile),
AbstractCompileAction.findName(nodes))) {
return false;
}
}
if (switchWorkspace) {
if (java.awt.EventQueue.isDispatchThread()) {
ExecuteAction.changeWorkspace ();
} else {
Runnable run = new Runnable() {
public void run() {
ExecuteAction.changeWorkspace ();
}
};
try {
java.awt.EventQueue.invokeAndWait(run);
} catch (InterruptedException e) {
throw new ThreadDeath();
} catch (java.lang.reflect.InvocationTargetException e) {
Throwable t = e.getTargetException();
if (t instanceof Error) {
throw (Error) t;
} else if (t instanceof RuntimeException) {
throw (RuntimeException) t;
} else { // cannot happen
if (Boolean.getBoolean("netbeans.debug.exceptions")) { // NOI18N
t.printStackTrace();
}
}
}
}
}
// execute
execute(execute.iterator());
return true;
}
}
/*
* Log
* 27 Gandalf-post-FCS1.25.1.0 3/15/00 David Simonek japanese localization
* now works correctly
* 26 Gandalf 1.25 1/12/00 Ian Formanek NOI18N
* 25 Gandalf 1.24 12/15/99 Ales Novak #4915 again
* 24 Gandalf 1.23 12/14/99 Ales Novak #4915
* 23 Gandalf 1.22 10/22/99 Ian Formanek NO SEMANTIC CHANGE - Sun
* Microsystems Copyright in File Comment
* 22 Gandalf 1.21 7/26/99 Ian Formanek finetuned behavior when
* compilation is not requested before execution
* 21 Gandalf 1.20 7/21/99 Ales Novak deadlock
* 20 Gandalf 1.19 7/11/99 David Simonek window system change...
* 19 Gandalf 1.18 6/24/99 Jesse Glick Gosh-honest HelpID's.
* 18 Gandalf 1.17 6/9/99 Ian Formanek Fixed resources for
* package change
* 17 Gandalf 1.16 6/8/99 Ian Formanek ---- Package Change To
* org.openide ----
* 16 Gandalf 1.15 6/8/99 Ales Novak #1780
* 15 Gandalf 1.14 5/28/99 Ian Formanek Cleaned up source
* (imports, ... - no semantic/english text change)
* 14 Gandalf 1.13 5/28/99 Ian Formanek Fixed bug 1692 - When an
* out-of-date class is executed, the compilation is run and it fails, the
* workspace is switched to "Running" anyway.
* 13 Gandalf 1.12 5/15/99 Jesse Glick [JavaDoc]
* 12 Gandalf 1.11 5/15/99 Ales Novak prev revision changed to
* enumerations
* 11 Gandalf 1.10 5/14/99 Ales Novak bugfix for #1667 #1598
* #1625
* 10 Gandalf 1.9 5/2/99 Ian Formanek Fixed last change
* 9 Gandalf 1.8 5/2/99 Ian Formanek Obsoleted
* help->DEFAULT_HELP
* 8 Gandalf 1.7 4/2/99 Jaroslav Tulach Compiles before
* execution.
* 7 Gandalf 1.6 3/26/99 Jesse Glick [JavaDoc]
* 6 Gandalf 1.5 2/17/99 Ian Formanek Updated icons to point
* to the right package (under ide/resources)
* 5 Gandalf 1.4 2/12/99 Ian Formanek Reflected renaming
* Desktop -> Workspace
* 4 Gandalf 1.3 1/20/99 Ales Novak
* 3 Gandalf 1.2 1/7/99 Ian Formanek fixed resource names
* 2 Gandalf 1.1 1/6/99 Ales Novak
* 1 Gandalf 1.0 1/5/99 Ian Formanek
* $
*/